﻿
using SIG.Basic.Extensions;
using SIG.Infrastructure.Cache;
using SIG.Infrastructure.Configs;
using SIG.Infrastructure.Logging;
using SIG.Model.FQAs;
using SIG.Repository;
using SIG.Resources;
using SIG.Resources.Admin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

namespace SIG.Service
{
    public class QuestionService: EntityService<Question>, IQuestionService
    {
      
        private readonly IQuestionRepository _questionRepository;
        private readonly ILoggingService _loggingService;
        private readonly ICacheService _cacheService;

        public QuestionService(IQuestionRepository questionRepository, ILoggingService loggingService, ICacheService cacheService)
            : base(questionRepository, cacheService, loggingService)
        {
         
            _questionRepository = questionRepository;
            _loggingService = loggingService;
            _cacheService = cacheService;
        }

        public async Task<IList<Question>> GetActiveElementsAync(CancellationToken cancellationToken = default(CancellationToken))
        {
            //get list
            var key = $"{EntityNames.Question}_List_Active";

            IList<Question> questionlist;
            if (SettingsManager.Question.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    questionlist = (IList<Question>)_cacheService.Get(key);

                }
                else
                {
                    var question = await _questionRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.Category);
                    questionlist = question.ToList();
                    _cacheService.Set(key, questionlist, SettingsManager.Question.CacheDuration);
                }
            }
            else
            {
                var questions = await _questionRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.Category);
                questionlist = questions.ToList();
            }

            return questionlist;

        }



        public Question GetQuestionDetail(int id)
        {
            return _questionRepository.GetFirstOrDefault(m => m.Id == id, m => m.Category);
        }

        public List<Question> GetPagedActiveElements(int pageIndex, int pageSize, string keyword, int? categoryId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Question}_ListCount_Active_{keyword}_{categoryId}";

            var totalIQuery = _questionRepository.GetAllElements().Where(g => g.Active);
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Title.Contains(keyword));
            if (categoryId > 0)
                totalIQuery = totalIQuery.Where(g => g.CategoryId == categoryId);

            if (SettingsManager.Question.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Question.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Question}_List_Active_{pageIndex}_{pageSize}_{keyword}_{categoryId}";

            List<Question> question;
            Expression<Func<Question, bool>> filter = g => g.Active;
            Expression<Func<Question, bool>> filterByKeyword = g => g.Title.Contains(keyword);
            Expression<Func<Question, bool>> filterByCategory = g => g.CategoryId == categoryId;

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (categoryId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Question.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    question = (List<Question>)_cacheService.Get(key);

                }
                else
                {
                    question = _questionRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.Category).ToList();
                    _cacheService.Set(key, question, SettingsManager.Question.CacheDuration);
                }
            }
            else
            {
                question = _questionRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.Category).ToList();
            }

            return question;

        }

       

        public int GetQuestionsCount()
        {

            var key = $"{EntityNames.Question}s_SearchCount";

            if (!SettingsManager.Question.EnableCaching)
            {
                return _questionRepository.GetAllElements().Count();
            }

            if (_cacheService.IsSet(key))
            {
                return (int)_cacheService.Get(key);
            }

            int questionsCount = _questionRepository.GetAllElements().Count();
            _cacheService.Set(key, questionsCount, SettingsManager.Question.CacheDuration);

            return questionsCount;
        }

        public int GetQuestionsCount(int blogId)
        {
            if (blogId == 0)
                return GetQuestionsCount();
            
            var key = $"{EntityNames.Question}s_SearchCount_{blogId}";

            if (!SettingsManager.Question.EnableCaching)
            {
               return _questionRepository.GetFilteredElements((a=>a.CategoryId == blogId)).Count();
            }
                            
            if (_cacheService.IsSet(key))
            {
               return (int)_cacheService.Get(key);
            }

            int questionsCount = _questionRepository.GetFilteredElements((a => a.CategoryId == blogId)).Count();
            _cacheService.Set(key, questionsCount, SettingsManager.Question.CacheDuration);
        
            return questionsCount;
        }

        

        public List<Question> GetPagedElements(int pageIndex, int pageSize, string keyword, int? categoryId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Question}_ListCount_{keyword}_{categoryId}";

            var totalIQuery = _questionRepository.GetAllElements();
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Title.Contains(keyword));
            if (categoryId > 0)
                totalIQuery = totalIQuery.Where(g => g.CategoryId == categoryId);

            if (SettingsManager.Question.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Question.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Question}_List_{pageIndex}_{pageSize}_{keyword}_{categoryId}";

            List<Question> questions;
            Expression<Func<Question, bool>> filter = g => true;
            Expression<Func<Question, bool>> filterByKeyword = g => g.Title.Contains(keyword);
            Expression<Func<Question, bool>> filterByCategory = g => g.CategoryId == categoryId;

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (categoryId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Question.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    questions = (List<Question>)_cacheService.Get(key);
                }
                else
                {
                    questions = _questionRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.Category).ToList();
                    _cacheService.Set(key, questions, SettingsManager.Question.CacheDuration);
                }
            }
            else
            {
                questions = _questionRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.Category).ToList();
            }

            return questions;

        }




        public IEnumerable<Question> LatesterQuestions(int count)
        {
            var key = $"{EntityNames.Question}s_Latester_{count}";

            if (!SettingsManager.Question.EnableCaching)
            {
                return _questionRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active,  false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Question>)_cacheService.Get(key);

            }

            var questionList = _questionRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active , false).ToList();
            _cacheService.Set(key, questionList, SettingsManager.Question.CacheDuration);


            return questionList;
        }
        public IEnumerable<Question> LatesterQuestions(int count,int categoryId)
        {
            if (categoryId == 0)
                return LatesterQuestions(count);

            var key = $"{EntityNames.Question}s_Latester_{count}_{categoryId}";
            if (!SettingsManager.Question.EnableCaching)
            {
                return _questionRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active & p.CategoryId == categoryId, false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Question>)_cacheService.Get(key);

            }

            var questionList = _questionRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active & p.CategoryId == categoryId, false).ToList();
            _cacheService.Set(key, questionList, SettingsManager.Question.CacheDuration);


            return questionList;
        }


    }
}
